import { useCallback, useState, useEffect, useRef, useMemo } from "react";
import ReactFlow, {
  MiniMap,
  Controls,
  Background,
  addEdge,
  Node,
  Edge,
  Connection,
  useNodesState,
  useEdgesState,
  getBezierPath,
  useReactFlow,
  ReactFlowProvider,
  EdgeProps,
} from "reactflow";
import "reactflow/dist/style.css";
import "./AIFlowCanvas.css";

import NodePanel from "./NodePanel";
import AINode from "./nodes/AINode";
import InputNode from "./nodes/InputNode";
import OutputNode from "./nodes/OutputNode";
import ProcessorNode from "./nodes/ProcessorNode";
import NodeConfigPanel from "./NodeConfigPanel";

interface NodeData {
  label: string;
  config: Record<string, unknown>;
}

// 初始节点和边
const initialNodes: Node<NodeData>[] = [];
const initialEdges: Edge[] = [];

// 自定义边组件，不要直接引用组件内部状态
function CustomEdge({
  id,
  sourceX,
  sourceY,
  targetX,
  targetY,
  sourcePosition,
  targetPosition,
  style = {},
  markerEnd,
  data,
}: EdgeProps) {
  const [edgePath, labelX, labelY] = getBezierPath({
    sourceX,
    sourceY,
    sourcePosition,
    targetX,
    targetY,
    targetPosition,
  });

  // 手动计算边的中心点
  const centerX = (sourceX + targetX) / 2;
  const centerY = (sourceY + targetY) / 2;

  const onEdgeClick = (evt: React.MouseEvent, id: string) => {
    evt.stopPropagation();
    if (data?.onAddNode) {
      // 调用添加节点函数，传递边ID和位置信息
      data.onAddNode(id, centerX, centerY);
    }
  };

  return (
    <>
      <path
        id={id}
        style={style}
        className="react-flow__edge-path"
        d={edgePath}
        markerEnd={markerEnd}
      />
      <foreignObject
        width={24}
        height={24}
        x={centerX - 12}
        y={centerY - 12}
        requiredExtensions="http://www.w3.org/1999/xhtml"
        className="edge-button-container"
      >
        <div
          className="edge-add-button"
          onClick={(event) => onEdgeClick(event, id)}
        >
          +
        </div>
      </foreignObject>
    </>
  );
}

// 必须在组件外部定义这些对象，并且不使用TypeScript的as const断言
const nodeTypes = {
  aiNode: AINode,
  inputNode: InputNode,
  outputNode: OutputNode,
  processorNode: ProcessorNode,
};

// 边类型也必须作为常量定义在外部
const edgeTypes = {
  custom: CustomEdge,
};

function AIFlowCanvas() {
  const [nodes, setNodes, onNodesChange] =
    useNodesState<NodeData>(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
  const [selectedNode, setSelectedNode] = useState<Node<NodeData> | null>(null);
  const reactFlowWrapper = useRef<HTMLDivElement>(null);

  // 使用useReactFlow钩子获取实例
  const reactFlowInstance = useReactFlow();

  // 添加节点选择面板的状态
  const [nodeMenuPosition, setNodeMenuPosition] = useState<{
    x: number;
    y: number;
    edgeId: string;
    // 新增：存储原始坐标，因为节点位置需要使用这个
    pageX: number;
    pageY: number;
  } | null>(null);

  // 在边上添加节点的处理函数 - 使用useCallback确保稳定引用
  const handleAddNodeOnEdge = useCallback(
    (edgeId: string, x: number, y: number) => {
      // 修复：边坐标是相对于视口的，需要转换为流程图坐标
      const { left, top } =
        reactFlowWrapper.current?.getBoundingClientRect() || {
          left: 0,
          top: 0,
        };
      const position = reactFlowInstance.project({
        x: x - left,
        y: y - top,
      });

      setNodeMenuPosition({
        x: x - left, // 菜单显示需要相对于wrapper的坐标
        y: y - top,
        pageX: x,
        pageY: y, // 保存原始坐标
        edgeId,
      });
    },
    [reactFlowInstance]
  );

  // 计算新节点位置，避免节点重叠
  const getNewNodePosition = useCallback(() => {
    // 网格大小，用于使节点整齐排列
    const gridSize = 20;
    const nodeWidth = 160; // 节点宽度 + 边距
    const nodeHeight = 100; // 节点高度 + 边距

    // 如果画布上没有节点，则放置在初始位置
    if (nodes.length === 0) {
      return { x: 100, y: 100 };
    }

    // 尝试找一个可用位置
    // 先检查是否可以放在当前行上
    const usedPositions = new Set();
    let maxY = 0;

    // 收集所有已占用位置
    nodes.forEach((node) => {
      usedPositions.add(
        `${Math.round(node.position.x / gridSize) * gridSize},${
          Math.round(node.position.y / gridSize) * gridSize
        }`
      );
      maxY = Math.max(maxY, node.position.y);
    });

    // 检查当前行的可用位置
    for (let x = 100; x < 2000; x += nodeWidth) {
      const roundedX = Math.round(x / gridSize) * gridSize;
      const roundedY = Math.round(maxY / gridSize) * gridSize;

      // 避免节点过于靠近边缘
      if (roundedX > 1800) continue;

      // 如果位置未被占用，就使用这个位置
      if (!usedPositions.has(`${roundedX},${roundedY}`)) {
        return { x: roundedX, y: roundedY };
      }
    }

    // 如果当前行已满，则在下一行开始新位置
    return { x: 100, y: maxY + nodeHeight };
  }, [nodes]);

  // 添加新节点
  const onAddNode = useCallback(
    (type: string, label: string) => {
      // 获取新节点的位置，避免重叠
      const position = getNewNodePosition();

      const newNode: Node<NodeData> = {
        id: `${type}-${Date.now()}`,
        type,
        position,
        data: { label, config: {} },
        // 添加更小的节点尺寸
        style: {
          width: 140,
          fontSize: "11px",
        },
      };
      setNodes((nds) => [...nds, newNode]);
    },
    [setNodes, getNewNodePosition]
  );

  // 添加新节点到边上
  const addNodeToEdge = useCallback(
    (type: string, label: string) => {
      if (!nodeMenuPosition) return;

      const { edgeId, pageX, pageY } = nodeMenuPosition;

      // 找到要修改的边
      const edge = edges.find((e) => e.id === edgeId);
      if (!edge) return;

      // 创建新节点 - 使用流程图坐标系
      const { left, top } =
        reactFlowWrapper.current?.getBoundingClientRect() || {
          left: 0,
          top: 0,
        };
      const position = reactFlowInstance.project({
        x: pageX - left,
        y: pageY - top,
      });

      const newNodeId = `${type}-${Date.now()}`;
      const newNode: Node<NodeData> = {
        id: newNodeId,
        type,
        // 使节点居中于点击位置
        position: {
          x: position.x - 70,
          y: position.y - 30,
        },
        data: { label, config: {} },
        style: {
          width: 140,
          fontSize: "11px",
        },
      };

      // 添加新节点
      setNodes((nds) => [...nds, newNode]);

      // 创建两条新的边: 原始源节点 -> 新节点, 新节点 -> 原始目标节点
      const newEdges = [
        {
          id: `edge-${Date.now()}-1`,
          source: edge.source,
          target: newNodeId,
          sourceHandle: edge.sourceHandle,
          targetHandle: "target-left",
          type: "custom",
          style: { stroke: "#86efac", strokeWidth: 1 },
          markerEnd: {
            type: "arrowclosed",
            width: 15,
            height: 15,
            color: "#86efac",
          },
          data: { onAddNode: handleAddNodeOnEdge },
        },
        {
          id: `edge-${Date.now()}-2`,
          source: newNodeId,
          target: edge.target,
          sourceHandle: "source-right",
          targetHandle: edge.targetHandle,
          type: "custom",
          style: { stroke: "#86efac", strokeWidth: 1 },
          markerEnd: {
            type: "arrowclosed",
            width: 15,
            height: 15,
            color: "#86efac",
          },
          data: { onAddNode: handleAddNodeOnEdge },
        },
      ];

      // 移除原始边，添加新的边
      setEdges((eds) => eds.filter((e) => e.id !== edgeId).concat(newEdges));

      // 关闭节点菜单
      setNodeMenuPosition(null);
    },
    [nodeMenuPosition, edges, setNodes, setEdges, reactFlowInstance]
  );

  // 处理连接 - 支持多连接并使用贝塞尔曲线
  const onConnect = useCallback(
    (params: Connection) => {
      const newEdgeId = `edge-${Date.now()}`;
      setEdges((eds) =>
        addEdge(
          {
            ...params,
            id: newEdgeId,
            animated: false,
            type: "custom", // 使用自定义边类型
            style: {
              strokeWidth: 1,
              stroke: "#86efac",
              curvature: 0.2,
            },
            markerEnd: {
              type: "arrowclosed",
              width: 15,
              height: 15,
              color: "#86efac",
            },
            data: { onAddNode: handleAddNodeOnEdge }, // 传递添加节点处理函数
            label:
              params.sourceHandle?.includes("left") &&
              params.targetHandle?.includes("right")
                ? "默认流"
                : undefined,
          },
          eds
        )
      );
    },
    [setEdges, handleAddNodeOnEdge]
  );

  // 处理节点点击
  const onNodeClick = useCallback(
    (_: React.MouseEvent, node: Node<NodeData>) => {
      setSelectedNode(node);
    },
    []
  );

  // 删除节点
  const onDeleteNode = useCallback(
    (nodeId: string) => {
      // 删除与该节点相关的所有边
      setEdges((eds) =>
        eds.filter((edge) => edge.source !== nodeId && edge.target !== nodeId)
      );

      // 删除节点
      setNodes((nds) => nds.filter((node) => node.id !== nodeId));

      // 如果删除的是当前选中的节点，则清空选中状态
      if (selectedNode && selectedNode.id === nodeId) {
        setSelectedNode(null);
      }
    },
    [selectedNode, setNodes, setEdges]
  );

  // 更新节点配置
  const updateNodeConfig = useCallback(
    (nodeId: string, config: Record<string, unknown>) => {
      setNodes((nds) =>
        nds.map((node) => {
          if (node.id === nodeId) {
            return {
              ...node,
              data: {
                ...node.data,
                config,
              },
            };
          }
          return node;
        })
      );
    },
    [setNodes]
  );

  // 键盘快捷键处理
  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (
        (event.key === "Delete" || event.key === "Backspace") &&
        selectedNode
      ) {
        onDeleteNode(selectedNode.id);
      }
    };

    document.addEventListener("keydown", handleKeyDown);
    return () => {
      document.removeEventListener("keydown", handleKeyDown);
    };
  }, [selectedNode, onDeleteNode]);

  // 保存工作流
  const saveWorkflow = useCallback(() => {
    const workflow = { nodes, edges };
    localStorage.setItem("ai-workflow", JSON.stringify(workflow));
    alert("工作流已保存!");
  }, [nodes, edges]);

  // 加载工作流
  const loadWorkflow = useCallback(() => {
    const savedWorkflow = localStorage.getItem("ai-workflow");
    if (savedWorkflow) {
      const { nodes: savedNodes, edges: savedEdges } =
        JSON.parse(savedWorkflow);
      setNodes(savedNodes);
      setEdges(savedEdges);
    }
  }, [setNodes, setEdges]);

  // 处理背景点击关闭节点菜单
  const onPaneClick = useCallback(() => {
    setNodeMenuPosition(null);
  }, []);

  // 转换现有的边为自定义边
  useEffect(() => {
    setEdges((eds) =>
      eds.map((edge) => ({
        ...edge,
        type: "custom",
        data: { ...edge.data, onAddNode: handleAddNodeOnEdge },
      }))
    );
  }, [handleAddNodeOnEdge]);

  // 缓存edgeOptions以避免每次渲染创建新对象
  const defaultEdgeOptions = useMemo(
    () => ({
      type: "custom",
      style: {
        strokeWidth: 2,
        stroke: "#86efac",
        curvature: 0.4,
      },
      markerEnd: {
        type: "arrowclosed",
        width: 15,
        height: 15,
        color: "#86efac",
      },
      data: { onAddNode: handleAddNodeOnEdge },
    }),
    [handleAddNodeOnEdge]
  );

  return (
    <div className="flow-container">
      <NodePanel onAddNode={onAddNode} />
      <div className="flow-wrapper" ref={reactFlowWrapper}>
        <div className="flow-content">
          <ReactFlow
            nodes={nodes}
            edges={edges}
            onNodesChange={onNodesChange}
            onEdgesChange={onEdgesChange}
            onConnect={onConnect}
            onNodeClick={onNodeClick}
            onPaneClick={onPaneClick}
            nodeTypes={nodeTypes}
            edgeTypes={edgeTypes}
            connectOnClick={false}
            fitView
            defaultEdgeOptions={defaultEdgeOptions}
          >
            <Controls />
            <MiniMap />
            <Background variant="dots" gap={12} size={1} color="#aaa" />

            {/* 节点选择菜单 - 放在ReactFlow组件内部以获得正确的坐标系统 */}
            {nodeMenuPosition && (
              <div
                className="node-selection-menu"
                style={{
                  position: "absolute",
                  left: nodeMenuPosition.x,
                  top: nodeMenuPosition.y,
                }}
              >
                <div className="menu-title">选择节点类型</div>
                <div className="menu-options">
                  <button onClick={() => addNodeToEdge("aiNode", "AI模型")}>
                    AI模型
                  </button>
                  <button
                    onClick={() => addNodeToEdge("processorNode", "处理器")}
                  >
                    处理器
                  </button>
                  <button
                    onClick={() => addNodeToEdge("outputNode", "输出节点")}
                  >
                    输出节点
                  </button>
                </div>
              </div>
            )}
          </ReactFlow>
        </div>
      </div>

      {selectedNode && (
        <NodeConfigPanel
          node={selectedNode}
          onClose={() => setSelectedNode(null)}
          updateNodeConfig={(config) =>
            updateNodeConfig(selectedNode.id, config)
          }
          onDeleteNode={() => onDeleteNode(selectedNode.id)}
        />
      )}
      <div className="workflow-actions">
        <button className="action-btn action-btn-save" onClick={saveWorkflow}>
          保存工作流
        </button>
        <button className="action-btn" onClick={loadWorkflow}>
          加载工作流
        </button>
      </div>
    </div>
  );
}

// 分离导入和定义，避免导入顺序问题
function WrappedAIFlowCanvas() {
  return (
    <ReactFlowProvider>
      <AIFlowCanvas />
    </ReactFlowProvider>
  );
}

export default WrappedAIFlowCanvas;
